<table class="example-table" mat-table editable [dataSource]="dataSource">
  <!--
    This edit lens is specified outside of the cell and must explicitly declare
    its context. It could be reused in multiple cells.
  -->
  <ng-template #weightEdit let-element>
    <div>
      <form #f="ngForm"
          matEditLens
          (ngSubmit)="onSubmitWeight(element, f)"
          [(matEditLensPreservedFormValue)]="weightValues.for(element).value">
        <div mat-edit-content>
          <mat-form-field>
            <input matInput type="number" [ngModel]="element.weight" name="weight" required>
          </mat-form-field>
        </div>
      </form>
    </div>
  </ng-template>

  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef> No. </th>
    <td mat-cell *matCellDef="let element">
      {{element.position}}

      <!-- Row hover content in a non-edit cell. -->
      <span *matRowHoverContent>
        <button mat-icon-button (click)="goodJob(element)">
          <mat-icon>thumb_up</mat-icon>
        </button>
        <button mat-icon-button (click)="badJob(element)">
          <mat-icon>thumb_down</mat-icon>
        </button>
      </span>
    </td>
  </ng-container>

  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef>
      Name
      <mat-checkbox
          [(ngModel)]="nameEditEnabled">Edit enabled</mat-checkbox>
    </th>
    <td mat-cell *matCellDef="let element"
        [matPopoverEdit]="nameEdit"
        [matPopoverEditDisabled]="!nameEditEnabled">
      {{element.name}}
      
      <!-- This edit is defined in the cell and can implicitly access element -->
      <ng-template #nameEdit>
        <div>
          <form #f="ngForm"
              matEditLens
              (ngSubmit)="onSubmitName(element, f)"
              [(matEditLensPreservedFormValue)]="nameValues.for(element).value">
            <h2 mat-edit-title>Name</h2>
            <div mat-edit-content>
              <mat-form-field>
                <input matInput [ngModel]="element.name" name="name" required>
              </mat-form-field>
            </div>
            <div mat-edit-actions>
              <button mat-button type="submit">Confirm</button>
              <button mat-button matEditRevert>Revert</button>
              <button mat-button matEditClose>Close</button>
            </div>
          </form>
        </div>
      </ng-template>

      <ng-container *ngIf="nameEditEnabled">
        <span *matRowHoverContent>
          <button mat-icon-button matEditOpen><mat-icon>edit</mat-icon></button>
        </span>
      </ng-container>
    </td>
  </ng-container>

  <!-- Type Column -->
  <ng-container matColumnDef="type">
    <th mat-header-cell *matHeaderCellDef> Type </th>
    <td mat-cell *matCellDef="let element"
        [matPopoverEdit]="typeEdit">
      {{element.type}}

      <!-- This edit is defined in the cell and can implicitly access element -->
      <ng-template #typeEdit>
        <div>
          <form #f="ngForm"
              matEditLens
              matEditClose
              (ngSubmit)="onSubmitType(element, f)"
              [(matEditLensPreservedFormValue)]="typeValues.for(element).value">
            <div mat-edit-fill>
              <mat-selection-list [multiple]="false"
                  name="type"
                  [ngModel]="[element.type]"
                  (selectionChange)="f.ngSubmit.emit()"
                  aria-label="Element type">
                <mat-list-option *ngFor="let type of TYPES"
                    [value]="type">
                  {{type}}
                </mat-list-option>
              </mat-selection-list>
            </div>
          </form>
        </div>
      </ng-template>

      <span *matRowHoverContent>
        <button mat-icon-button matEditOpen><mat-icon>arrow_drop_down</mat-icon></button>
      </span>
    </td>
  </ng-container>

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <th mat-header-cell *matHeaderCellDef> Weight </th>
    <td mat-cell *matCellDef="let element"
        [matPopoverEdit]="weightEdit" [matPopoverEditContext]="element">
      {{element.weight}}
      
      <span *matRowHoverContent>
        <button mat-icon-button matEditOpen><mat-icon>edit</mat-icon></button>
      </span>
    </td>
  </ng-container>

  <!-- Symbol Column -->
  <ng-container matColumnDef="symbol">
    <th mat-header-cell *matHeaderCellDef> Symbol </th>
    <td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

  <!-- Fantasy Counterparts Column -->
  <ng-container matColumnDef="fantasyCounterpart">
    <th mat-header-cell *matHeaderCellDef> Fantasy Counterparts </th>
    <td mat-cell *matCellDef="let element"
        [matPopoverEdit]="fantasyCounterpartEdit">
      {{element.fantasyCounterparts.join(', ')}}

      <!-- This edit is defined in the cell and can implicitly access element -->
      <ng-template #fantasyCounterpartEdit>
        <div>
          <form #f="ngForm"
              matEditLens
              (ngSubmit)="onSubmitFantasyCounterparts(element, f)"
              [(matEditLensPreservedFormValue)]="fantasyValues.for(element).value">
            <div mat-edit-fill>
              <mat-selection-list [ngModel]="element.fantasyCounterparts"
                  name="fantasyCounterparts"
                  aria-label="Fantasy Element Counterparts">
                <mat-list-option *ngFor="let fantasyElement of FANTASY_ELEMENTS"
                    [value]="fantasyElement"
                    checkboxPosition="before">
                  {{fantasyElement}}
                </mat-list-option>
              </mat-selection-list>
            </div>
            <div mat-edit-actions>
              <button mat-button type="submit">Confirm</button>
              <button mat-button matEditRevert>Revert</button>
            </div>
          </form>
        </div>
      </ng-template>

      <span *matRowHoverContent>
        <button mat-icon-button matEditOpen><mat-icon>arrow_drop_down</mat-icon></button>
      </span>
    </td>
  </ng-container>
</table>
